/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium;

import java.io.File;
import java.io.IOException;

import fr.x9c.cadmium.gui.ParametersDialog;
import fr.x9c.cadmium.kernel.ByteCodeParameters;
import fr.x9c.cadmium.kernel.CadmiumException;
import fr.x9c.cadmium.kernel.Disassembler;
import fr.x9c.cadmium.kernel.Fail;
import fr.x9c.cadmium.kernel.Fatal;
import fr.x9c.cadmium.kernel.Interpreter;
import fr.x9c.cadmium.kernel.Misc;
import fr.x9c.cadmium.kernel.Value;
import fr.x9c.cadmium.util.RandomAccessInputStream;
import java.io.InputStream;

/**
 * Entry point of the Cadmium standalone interpreter.
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.3
 * @since 1.0
 */
public final class Main {

    /**
     * No instance of this class.
     */
    private Main() {
    } // end empty constructor

    /**
     * Entry point of the standalone interpreter. <br/>
     * Structure of command-line arguments:
     * <ul>
     *   <li>first ones: arguments begining by <tt>--</tt>;</li>
     *   <li>then: name of bytecode file;</li>
     *   <li>then: arguments to application.</li>
     * </ul>
     * @param args arguments to application
     */
    public static int main(InputStream byteStream, final String[] args) {
        try {
            // interpreter parameters
            final File currentDir = new File(".");
            final ByteCodeParameters commandLineParams =
                ByteCodeParameters.fromArray(args, Misc.isWindowPlatform()
                                             ? currentDir
                                             : null);
            final ByteCodeParameters dialogParams =
                commandLineParams.showDialog()
                ? ParametersDialog.open(commandLineParams)
                : null;
            final ByteCodeParameters params = dialogParams != null
                ? dialogParams
                : commandLineParams;

            if (params.showHelp()) {
                ByteCodeParameters.printUsage(System.out);
                System.exit(0);
            } else if (params.showVersion()) {
                System.out.println(Infos.VERSION);
//                System.exit(0);
                return 0;
            } // end if/elsif

            // interpreter execution
//            final String filename = params.getFile();
//            if (filename != null) {
//                final RandomAccessInputStream bytecode =
//                    new RandomAccessInputStream(filename);
//                final Interpreter interpreter = new Interpreter(params,
//                                                                currentDir,
//                                                                bytecode);
                final RandomAccessInputStream bytecode =
                    new RandomAccessInputStream(byteStream);
                final Interpreter interpreter = new Interpreter(params,
                                                                currentDir,
                                                                bytecode);

                bytecode.close();
                if (params.showDisassembled()) {
                    Disassembler.disassembleAll(interpreter.getContext(),
                                                System.out);
                } // end if
                final Value res = interpreter.execute();
                return((res != null) && res.isLong() ? res.asLong() : 0);
//            } else {
//                System.exit(1);
//            } // end if
        } catch (final Fatal.Exception fatal) {
            System.out.println("fatal error: " + fatal.getMessage());
//            System.exit(1);
            return 1;
        } catch (final IOException ioe) {
            System.out.println("i/o error: " + ioe.getMessage());
//            System.exit(1);
            return 1;
        } catch (final CadmiumException ie) {
            final Throwable t = ie.getCause();
            if (!(t instanceof Fail.Exception)
                && !(t instanceof Fatal.Exception)) {
                System.out.println("error: " + ie.getMessage());
            } // end if
//            System.exit(1);
            return 1;
        } catch (final Exception e) {
            System.out.println("internal error: " + e.getMessage());
            e.printStackTrace(System.err);
//            System.exit(1);
            return 1;
        } catch (final Throwable t) {
            System.out.println("Java error: " + t.getMessage());
            t.printStackTrace(System.err);
//            System.exit(1);
            return 1;
        } // end try/catch
    } // end method 'main(String[])'

} // end class 'Main'
